#include "dask.h"
DiskArm::DiskArm(){
	int i;
	//输入当前道号
	cout << "Please input Current cylinder :" ;
	cin >> CurrentCylinder;
	//磁头方向,输入 0 表示向小道号移动,1 表示向大道号移动
	cout << "Please input Current Direction (0/1) :" ;
	cin >> SeekDirection;
	//输入磁盘请求数,请求道号
	cout << "Please input Request Numbers :" ;
	cin >> RequestNumber;
	cout << "Please input Request cylinder string :";
	Request = new int[RequestNumber];
	Cylinder = new int[RequestNumber];
	for (i = 0; i < RequestNumber; i++)
		cin >> Request[i];
	MaxCylinder=199;
}
DiskArm::~DiskArm(){
	delete []Request;	//析构数组
	delete []Cylinder;
}
//初始化道号,寻道记录
void DiskArm::InitSpace(const char * MethodName)
{
	int i;
	cout << endl << MethodName << endl;	//打印寻道方法
	SeekNumber = 0;	//初始化移臂总数
	SeekChang = 0;	//初始化磁头掉头数
	for (i = 0; i < RequestNumber; i++)
		Cylinder[i] = Request[i];	//为请求赋值
}
// 统计报告算法执行情况
void DiskArm::Report(void){
	cout << endl;
	cout << "Seek Number: " << SeekNumber << endl;
	cout << "Chang Direction: " << SeekChang << endl << endl;
}
//先来先服务算法
void DiskArm::Fcfs(void)
{
	int Current = CurrentCylinder;
	int Direction = SeekDirection;
	InitSpace("FCFS");
	cout << Current;
	for(int i=0; i<RequestNumber; i++){
	if(((Cylinder[i] >= Current) && !Direction)||((Cylinder[i] < Current) && Direction)){
	//需要调头
		SeekChang++; //调头数加 1
		Direction = !Direction ; //改变方向标志
	//报告当前响应的道号
	cout << endl << Current << " -> " << Cylinder[i];
	}else //不需调头,报告当前响应的道号
		cout << " -> " << Cylinder[i] ;
		//累计寻道数,响应过的道号变为当前道号
		SeekNumber += abs(Current -Cylinder[i]);
		Current = Cylinder[i];
	}
	//报告磁盘移臂调度的情况
	Report();
}
//最短寻道时间优先算法
void DiskArm::Sstf(void)
{
	int Shortest;
	int Distance = 999999 ;
	int Direction = SeekDirection;
	int Current = CurrentCylinder;
	InitSpace("SSTF");
	cout << Current;
	for(int i=0; i<RequestNumber; i++){
		//查找当前最近道号
		for(int j=0; j<RequestNumber; j++){
			if(Cylinder[j] == -1) continue; //-1 表示已经响应过了
				if(Distance > abs(Current-Cylinder[j])){
					//到下一道号比当前距离近,下一道号为当前距离
					Distance = abs(Current-Cylinder[j]);
					Shortest = j;
				}
		}
			if((( Cylinder[Shortest] >= Current) && !Direction)||(( Cylinder[Shortest] < CurrentCylinder) && Direction)){
				//需要调头
				SeekChang++; //调头数加 1
				Direction = !Direction ; //改变方向标志
				//报告当前响应的道号
				cout << endl << Current << " -> " << Cylinder[Shortest];
			}
			else //不需调头,报告当前响应的道号
				cout << " -> " << Cylinder[Shortest] ;
		//累计寻道数,响应过的道号变为当前道号
		SeekNumber += abs(Current -Cylinder[Shortest]);
		Current = Cylinder[Shortest];
		//恢复最近距离,销去响应过的道号
		Distance = 999999;
		Cylinder[Shortest] = -1;
	}
	Report();
}
//电梯调度算法
void DiskArm::Scan(void)
{
	int Direction = SeekDirection;	//获取当前方向
	int Current = CurrentCylinder;	//获取当前磁道
	InitSpace("SCAN");	//初始化相关数据
	cout <<Current;	//打印当前磁道
	sort(Cylinder,Cylinder+RequestNumber);//排序请求，便于计算
	int start=Current;	//开始的位置
	cout<<endl<<Current;
	for(int i=start;i>0;i--){	//向小道搜索
		for(int j=0;j<RequestNumber;j++){		//遍历所有请求
			if(i==Cylinder[j]){	//发现匹配
				cout<<" -> "<<Cylinder[j];
				SeekNumber+=Current-Cylinder[j];	//更新SeekNmber
				Current=Cylinder[j];	//更新当前位置
				Cylinder[j]=-1;//表示已经处理
				break;//继续前进
			}
		}
	}
	if(Cylinder[RequestNumber-1]>0){	//如果掉头
		SeekChang++;	//掉头数增加
		SeekNumber+=Current;	//计算剩余距离
		Current=0;
		cout<<" -> "<<0<<endl<<0;	//打印掉头后状况
		for(int i=0;i<MaxCylinder;i++){
			for(int j=0;j<RequestNumber;j++){		//遍历所有请求
				if(i==Cylinder[j]){	//发现匹配
					cout<<" -> "<<Cylinder[j];
					SeekNumber+=Cylinder[j]-Current;	//更新SeekNmber
					Current=Cylinder[j];	//更新当前位置
					Cylinder[j]=-1;//表示已经处理
					break;//继续前进
				}
			}
		}
	}
	Report();
}
//均匀电梯调度算法，默认向大号为处理
void DiskArm::CScan(void){
	int Direction = SeekDirection;
	int Current = CurrentCylinder;
	InitSpace("CSCAN");
	cout << Current;
	sort(Cylinder,Cylinder+RequestNumber);//排序请求，便于计算
	int start=0;	//开始的位置
	for(int i=0;i<RequestNumber;i++){
		start=i;
		if(Cylinder[i]-Current>0)//向大磁道移动,找出第一个在当前磁道右端的位置
			break;	//更新起点
	}
	int epo=(start==0?1:2);
	SeekChang=(epo-1)*2;//计算掉头次数
	if(epo!=1)	//如果一定会掉头
		SeekNumber+=2*MaxCylinder-Cylinder[RequestNumber-1];
	for(int i=0;i<epo;i++){	//根据start决定一遍还是两遍处理完
		cout<<endl<<Current;	//打印当前位置
		for(int j=start;j<RequestNumber;j++){
			if(Cylinder[j]>0){
				cout<<" -> "<<Cylinder[j];
				SeekNumber+=Cylinder[j]-Current;//更新寻道数
				Current=Cylinder[j];		//更新寻道号
				Cylinder[j]=-1;	//表示完成
			}
		}
		if(i!=epo-1)	cout<<" -> "<<MaxCylinder;
		Current=0;//更新位置
		start=0;
	}	
	Report();
}	
//LOOK 调度算法
void DiskArm::Look(void){
	int Direction = SeekDirection;
	int Current = CurrentCylinder;
	InitSpace("LOOK");
	cout << Current;
	sort(Cylinder,Cylinder+RequestNumber);//排序请求，便于计算
	int start=0;	//开始的位置
	for(int i=0;i<RequestNumber;i++){
		start=i;
		if(Cylinder[i]-Current>0)//向大磁道移动,找出第一个在当前磁道右端的位置
			break;	//更新起点
	}
	int epo=(start==0?1:2);
	SeekChang=(epo-1)*2;//计算掉头次数
	if(epo!=1)	//如果一定要掉头
		SeekNumber+=Cylinder[RequestNumber-1]-Cylinder[0];
	for(int i=0;i<epo;i++){	//根据start决定一遍还是两遍处理完
		cout<<endl<<Current;	//打印当前位置
		for(int j=start;j<RequestNumber;j++){
			if(Cylinder[j]>0){
				cout<<" -> "<<Cylinder[j];
				SeekNumber+=Cylinder[j]-Current;//更新寻道数
				Current=Cylinder[j];		//更新寻道号
				Cylinder[j]=-1;	//表示完成
			}
		}
		Current=Cylinder[0];//更新位置
		start=1;
	}	
	Report();
}
//程序启动入口
int main(int argc,char *argv[]){
	//建立磁盘移臂调度类
	DiskArm *dask = new DiskArm();
	//比较和分析 FCFS 和 SSTF 两种调度算法的性能
	dask->Fcfs();
	dask->Sstf();
	dask->Scan();
	dask->CScan();
	dask->Look();
}
